package fi.bluepill.server.rest;


import com.mongodb.DBObject;
import com.mongodb.util.JSON;
import fi.bluepill.server.AuthenticationException;
import fi.bluepill.server.FileStorage;
import fi.bluepill.server.LocalFileStorage;
import fi.bluepill.server.S3FileStorage;
import fi.bluepill.server.model.UserAccount;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
import org.owasp.esapi.ESAPI;
import org.owasp.esapi.crypto.CipherText;
import org.owasp.esapi.crypto.PlainText;
import rip.core.RIPService;

import javax.persistence.Query;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

public abstract class BluepillService extends RIPService {
    private FileStorage storage;
    private String userId;

    protected DBObject toDBObject(Object obj) {
        try {
            return (DBObject) JSON.parse(json().writeValueAsString(obj));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    protected ObjectNode okMessage() {
        ObjectNode msg = newMessage();
        msg.put("status", "ok");
        return msg;
    }

    protected void write(DBObject object) {
        try {
            getoutOutputStream().write(JSON.serialize(object).getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    protected UserAccount user(String uuid) {
        Query q = jpa().createQuery("select ua from UserAccount ua where ua.uuid = :uuid");
        q.setParameter("uuid", uuid);

        List<UserAccount> result = q.getResultList();

        if (result.size() == 0)
            return null;

        if (result.size() > 1)
            throw new IllegalArgumentException("More than one user found with given uuid");

        return result.get(0);
    }

    protected FileStorage fileStorage() {
        if (storage == null) {
            if (isTestMode()) {
                File f = new File("tilecache");
                f.mkdir();

                storage = new LocalFileStorage(f);
            }
            else
                return new S3FileStorage();
        }

        return storage;
    }

    protected boolean isEmpty(String s) {
        if (s == null || s.length() == 0)
            return true;

        return false;
    }

    private Properties envProperties = null;




    protected void assertAuthentication() {
        if (cookie("bluepillAuth") == null)
            throw new AuthenticationException("This service requires login.");

        String authCookie = cookie("bluepillAuth");
        PlainText plainText = null;

        try {
            CipherText cipherText = CipherText.fromPortableSerializedBytes(ESAPI.encoder().decodeFromBase64(authCookie));
            plainText = ESAPI.encryptor().decrypt(cipherText);
        } catch (Exception e) {
            throw new AuthenticationException("Could not decrypt auth cookie", e);
        }

        JsonNode json = null;

        try {
            json = json().readTree(plainText.toString());
        } catch (IOException e) {
            throw new AuthenticationException("Could not read JSON");
        }

        long expires = json.get("expires").getLongValue();

        if (expires < System.currentTimeMillis())
            throw new AuthenticationException("Authentication expired");

        String originalIpAddress = json.get("ip").getTextValue();

        if (!originalIpAddress.equals(ipAddress()))
            throw new AuthenticationException("IP address mismatch");

        userId = json.get("uuid").getTextValue();
    }

    protected String userId() {
        if (userId == null)
            throw new AuthenticationException("No authentication check has been done.");

        return userId;
    }
}
